################################################
###### STANDARD INPUT_SHAPER CALIBRATIONS ######
################################################
# Written by Frix_x#0161 #
# @version: 1.1

# CHANGELOG:
#   v1.1: added M400 to validate that the files are correctly saved to disk
#   v1.0: first version of the automatic input shaper workflow

# -------------------------------------------------------------------------------------------------------------------------
# If you want to use it into your own config, please install it as a standalone macro as described in the
# installation section of this file: doc > features > is_workflow.md
# -------------------------------------------------------------------------------------------------------------------------

### What is it ? ###
# This macro helps you to configure the input shaper algorithm of Klipper by running the tests sequencially and calling an automatic script
# that generate the graphs, manage the files and so on. It's basically a fully automatic input shaper calibration workflow.
# Results can be found in your config folder using FLuidd/Maisail file manager.

# The goal is to make it easy to set, share and use it.

# Usage:
#   1. Call the AXES_SHAPER_CALIBRATION macro, wait for it to end and compute the graphs. Then look for the results in the results folder.
#   2. Call the BELTS_SHAPER_CALIBRATION macro, wait for it to end and compute the graphs. Then look for the results in the results folder.


[gcode_macro telegram_shaper]
description: график шейперов в телеграм
gcode:
	{% set HZ_PER_SEC = params.HZ_PER_SEC|default(1)|float %} #Parse parameters
	{% set POSITION_X = params.POSITION_X|default(125)|int %}
	{% set POSITION_Y = params.POSITION_Y|default(100)|int %}
	{% set POSITION_Z = params.POSITION_Z|default(30)|int %}

	{% if printer.toolhead.homed_axes != 'xyz' %} #home if not homed
		G28
	{% endif %}
	TEST_RESONANCES AXIS=X HZ_PER_SEC={ HZ_PER_SEC } POINT={ POSITION_X },{ POSITION_Y },{POSITION_Z}
	TEST_RESONANCES AXIS=Y HZ_PER_SEC={ HZ_PER_SEC } POINT={ POSITION_X },{ POSITION_Y },{POSITION_Z}
	RUN_SHELL_COMMAND CMD=shaper_calibrate
	RESPOND PREFIX=tg_send_image MSG="path=['/home/pi/printer_data/config/adxl_results/inputshaper/resonances_x.png', '/home/pi/printer_data/config/adxl_results/inputshaper/resonances_y.png'], message='Результат проверки шейперов' "




[gcode_macro telegram_BELTS_CALIBRATION]
description: график вибрации ремней принтера
gcode:
    {% set verbose = params.VERBOSE|default(true) %}
    
    TEST_RESONANCES AXIS=1,1 OUTPUT=raw_data NAME=b
    M400
    TEST_RESONANCES AXIS=1,-1 OUTPUT=raw_data NAME=a
    M400

    {% if verbose %}
        RESPOND MSG="Graphs generation... Please wait a minute or two and look in the configured folder."
    {% endif %}
    G4	 P10000 
    RUN_SHELL_COMMAND CMD=plot_graph PARAMS=BELTS
    RESPOND PREFIX=tg_send_image MSG="path=['/home/pi/printer_data/config/adxl_results/belts/belts.png'], message='график вибрации ремней принтера' "

[gcode_macro telegram_VIBRATIONS_CALIBRATION]
description: График резонансов на скорости
gcode:
    #
    # PARAMETERS
    #
    {% set size = params.SIZE|default(60)|int %} # size of the area where the movements are done
    {% set direction = params.DIRECTION|default('XY') %} # can be set to either XY, AB, ABXY, A, B, X, Y, Z
    {% set z_height = params.Z_HEIGHT|default(20)|int %} # z height to put the toolhead before starting the movements
    {% set verbose = params.VERBOSE|default(true) %} # Wether to log the current speed in the console

    {% set min_speed = params.MIN_SPEED|default(20)|int * 60 %} # minimum feedrate for the movements
    {% set max_speed = params.MAX_SPEED|default(200)|int * 60 %} # maximum feedrate for the movements
    {% set speed_increment = params.SPEED_INCREMENT|default(2)|int * 60 %} # feedrate increment between each move
    {% set feedrate_travel = params.TRAVEL_SPEED|default(200)|int * 60 %} # travel feedrate between moves

    {% set accel_chip = params.ACCEL_CHIP|default("adxl345") %} # ADXL chip name in the config

    #
    # COMPUTED VALUES
    #
    {% set mid_x = printer.toolhead.axis_maximum.x|float / 2 %}
    {% set mid_y = printer.toolhead.axis_maximum.y|float / 2 %}

    {% set direction_factor = {
        'XY'  : {
            'start' : {'x': -0.5, 'y': -0.5 },
            'move_factors' : {
                '0' : {'x': 0.5, 'y': -0.5, 'z': 0.0 },
                '1' : {'x': 0.5, 'y': 0.5, 'z': 0.0 },
                '2' : {'x': -0.5, 'y': 0.5, 'z': 0.0 },
                '3' : {'x': -0.5, 'y': -0.5, 'z': 0.0 }
                }
            },
        'AB' : {
            'start' : {'x': 0.0, 'y': 0.0 },
            'move_factors' : {
                '0' : {'x': 0.5, 'y': -0.5, 'z': 0.0 },
                '1' : {'x': -0.5, 'y': 0.5, 'z': 0.0 },
                '2' : {'x': 0.0, 'y': 0.0, 'z': 0.0 },
                '3' : {'x': 0.5, 'y': 0.5, 'z': 0.0 },
                '4' : {'x': -0.5, 'y': -0.5, 'z': 0.0 },
                '5' : {'x': 0.0, 'y': 0.0, 'z': 0.0 }
                }
            },
        'ABXY' : {
            'start' : {'x': -0.5, 'y': 0.5 },
            'move_factors' : {
                '0' : {'x': -0.5, 'y': -0.5, 'z': 0.0 },
                '1' : {'x': 0.5, 'y': -0.5, 'z': 0.0 },
                '2' : {'x': -0.5, 'y': 0.5, 'z': 0.0 },
                '3' : {'x': 0.5, 'y': 0.5, 'z': 0.0 },
                '4' : {'x': -0.5, 'y': -0.5, 'z': 0.0 },
                '5' : {'x': -0.5, 'y': 0.5, 'z': 0.0 }
                }
            },
        'B'  : {
            'start' : {'x': 0.5, 'y': 0.5 },
            'move_factors' : {
                '0' : {'x': -0.5, 'y': -0.5, 'z': 0.0 },
                '1' : {'x': 0.5, 'y': 0.5, 'z': 0.0 }
                }
            },
        'A'  : {
            'start' : {'x': -0.5, 'y': 0.5 },
            'move_factors' : {
                '0' : {'x': 0.5, 'y': -0.5, 'z': 0.0 },
                '1' : {'x': -0.5, 'y': 0.5, 'z': 0.0 }
                }
            },
        'X'  : {
            'start' : {'x': -0.5, 'y': 0.0 },
            'move_factors' : {
                '0' : {'x': 0.5, 'y': 0.0, 'z': 0.0 },
                '1' : {'x': -0.5, 'y': 0.0, 'z': 0.0 }
                }
            },
        'Y'  : {
            'start' : {'x': 0.0, 'y': 0.5 },
            'move_factors' : {
                '0' : {'x': 0.0, 'y': -0.5, 'z': 0.0 },
                '1' : {'x': 0.0, 'y': 0.5, 'z': 0.0 }
                }
            },
        'Z'  : {
            'start' : {'x': 0.0, 'y': 0.0 },
            'move_factors' : {
                '0' : {'x': 0.0, 'y': 0.0, 'z': 1.0 },
                '1' : {'x': 0.0, 'y': 0.0, 'z': 0.0 }
                }
            }
        }
    %}

    #
    # STARTING...
    #
    {% if not 'xyz' in printer.toolhead.homed_axes %}
        { action_raise_error("Must Home printer first!") }
    {% endif %}

    {% if (size / (max_speed / 60)) < 0.25 %}
        { action_raise_error("SIZE is too small for this MAX_SPEED. Increase SIZE or decrease MAX_SPEED!") }
    {% endif %}

    {% if not (direction in direction_factor) %}
        { action_raise_error("DIRECTION is not valid. Only XY, AB, ABXY, A, B, X, Y or Z is allowed!") }
    {% endif %}

    {action_respond_info("")}
    {action_respond_info("Starting speed and vibration calibration")}
    {action_respond_info("This operation can not be interrupted by normal means. Hit the \"emergency stop\" button to stop it if needed")}
    {action_respond_info("")}

    SAVE_GCODE_STATE NAME=STATE_VIBRATIONS_CALIBRATION

    G90

    # Going to the start position
    G1 Z{z_height}
    G1 X{mid_x + (size * direction_factor[direction].start.x) } Y{mid_y + (size * direction_factor[direction].start.y)} F{feedrate_travel}

    # vibration pattern for each frequency
    {% for curr_speed in range(min_speed, max_speed + speed_increment) %}
        {% if (curr_speed - min_speed) % speed_increment == 0 %}
            {% if verbose %}
                RESPOND MSG="Current speed: {(curr_speed / 60)|int} mm/s"
            {% endif %}

            ACCELEROMETER_MEASURE CHIP={accel_chip}
            {% for key, factor in direction_factor[direction].move_factors|dictsort %}
                G1 X{mid_x + (size * factor.x) } Y{mid_y + (size * factor.y)} Z{z_height + (size * factor.z)} F{curr_speed}
            {% endfor %}
            ACCELEROMETER_MEASURE CHIP={accel_chip} NAME=sp{(curr_speed / 60)|int}n1

            G4 P300
            M400
        {% endif %}
    {% endfor %}

    {% if verbose %}
        RESPOND MSG="Graphs generation... Please wait a minute or two and look in the configured folder."
    {% endif %}
    RUN_SHELL_COMMAND CMD=plot_graph PARAMS="VIBRATIONS {direction}"

    RESTORE_GCODE_STATE NAME=STATE_VIBRATIONS_CALIBRATION

    RESPOND PREFIX=tg_send_image MSG="path=['/home/pi/printer_data/config/adxl_results//vibrations/vibrations.png'], message='График резонансов на скорости' "

